Предисловие . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Введение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Глава 1. Чистый код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Да будет код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Плохой код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Расплата за хаос . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Грандиозная переработка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Отношение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Основной парадокс . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Искусство чистого кода? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Что такое «чистый код»? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Мы — авторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Правило бойскаута . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Предыстория и принципы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Глава 2. Содержательные имена (Тим Оттингер) . . . . . . . . . . . . . . . . . . . . . . . 39
Имена должны передавать намерения программиста . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Избегайте дезинформации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Используйте осмысленные различия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Используйте удобопроизносимые имена . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Выбирайте имена, удобные для поиска . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Избегайте схем кодирования имен . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Венгерская запись . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Префиксы членов классов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Интерфейсы и реализации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Избегайте мысленных преобразований . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Имена классов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Имена методов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Избегайте остроумия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Выберите одно слово для каждой концепции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Воздержитесь от каламбуров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Используйте имена из пространства решения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Используйте имена из пространства задачи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5
6   ﻿Содержание
Добавьте содержательный контекст . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Не добавляйте избыточный контекст . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Несколько слов напоследок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Глава 3. Функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Компактность! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Блоки и отступы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Правило одной операции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Секции в функциях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Один уровень абстракции на функцию ............................................ 61
Чтение кода сверху вниз: правило понижения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Команды switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Используйте содержательные имена . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Аргументы функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Стандартные унарные формы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Аргументы-флаги . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Бинарные функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Тернарные функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Объекты как аргументы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Списки аргументов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Глаголы и ключевые слова . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Избавьтесь от побочных эффектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Выходные аргументы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Разделение команд и запросов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Используйте исключения вместо возвращения кодов ошибок . . . . . . . . . . . . . . . . . . . . . 71
Изолируйте блоки try/catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Обработка ошибок как одна операция . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Магнит зависимостей Error.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Не повторяйтесь . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Структурное программирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Как научиться писать такие функции? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Завершение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Глава 4. Комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Комментарии не компенсируют плохого кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Объясните свои намерения в коде . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Хорошие комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Юридические комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Информативные комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Представление намерений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Прояснение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Предупреждения о последствиях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Комментарии TODO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Усиление . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Комментарии Javadoc в общедоступных API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Плохие комментарии ............................................................. 86
Бормотание . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Избыточные комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Недостоверные комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
6
Содержание      7
Обязательные комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Журнальные комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Шум . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Опасный шум . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Не используйте комментарии там, где можно использовать функцию
или переменную . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Позиционные маркеры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Комментарии за закрывающей фигурной скобкой . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Ссылки на авторов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Закомментированный код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Комментарии HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Нелокальная информация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Слишком много информации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Неочевидные комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Заголовки функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Заголовки Javadoc во внутреннем коде . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Глава 5. Форматирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Цель форматирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Вертикальное форматирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Газетная метафора . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Вертикальное разделение концепций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Вертикальное сжатие . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Вертикальные расстояния . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
Вертикальное упорядочение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Горизонтальное форматирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Горизонтальное разделение и сжатие . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Горизонтальное выравнивание . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Отступы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Вырожденные области видимости . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Правила форматирования в группах ......................................... 118
Правила форматирования от дядюшки Боба . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Глава 6. Объекты и структуры данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Абстракция данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Антисимметрия данных/объектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Закон Деметры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Крушение поезда . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Гибриды . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Скрытие структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Объекты передачи данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Активные записи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
Глава 7. Обработка ошибок (Майк Физерс) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Используйте исключения вместо кодов ошибок . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Начните с написания команды try-catch-finally . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
7
8   ﻿Содержание
Используйте непроверяемые исключения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
Передавайте контекст с исключениями . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Определяйте классы исключений в контексте потребностей
вызывающей стороны . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Определите нормальный путь выполнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Не возвращайте null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Не передавайте null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Глава 8. Границы (Джеймс Гренинг) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Использование стороннего кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Исследование и анализ границ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Изучение log4j .............................................................. 145
Учебные тесты: выгоднее, чем бесплатно . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Использование несуществующего кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Чистые границы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Глава 9. Модульные тесты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Три закона TTD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
О чистоте тестов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
Тесты как средство обеспечения изменений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Чистые тесты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Предметно-ориентированный язык тестирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Двойной стандарт . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Одна проверка на тест . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Одна концепция на тест . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
F.I.R.S.T. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Глава 10. Классы (совместно с Джеффом Лангром) . . . . . . . . . . . . . . . . . . . . . . 164
Строение класса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Инкапсуляция . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Классы должны быть компактными! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Принцип единой ответственности (SRP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Связность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Поддержание связности приводит к уменьшению классов .................... 170
Структурирование с учетом изменений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Изоляция изменений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Глава 11. Системы (Кевин Дин Уомплер)............................... 181
Как бы вы строили город? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
Отделение конструирования системы от ее использования . . . . . . . . . . . . . . . . . . . . . . . 182
Отделение main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Фабрики . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Внедрение зависимостей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
8
Оглавление    ﻿     9
Масштабирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Поперечные области ответственности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Посредники . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
АОП-инфраструктуры на «чистом» Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Аспекты AspectJ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Испытание системной архитектуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
Оптимизация принятия решений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Применяйте стандарты разумно, когда они приносят очевидную пользу . . . . . . . . . . 197
Системам необходимы предметно-ориентированные языки . . . . . . . . . . . . . . . . . . . 198
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Глава 12. Формирование архитектуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Четыре правила . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Правило № 1: выполнение всех тестов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Правила № 2–4: переработка кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Отсутствие дублирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Выразительность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Минимум классов и методов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
Глава 13. Многопоточность (Бретт Л. Шухерт) . . . . . . . . . . . . . . . . . . . . . . . . . 207
Зачем нужна многопоточность? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
Мифы и неверные представления . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Трудности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Защита от ошибок многопоточности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
Принцип единой ответственности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
Следствие: ограничивайте область видимости данных . . . . . . . . . . . . . . . . . . . . . . . . 211
Следствие: используйте копии данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Следствие: потоки должны быть как можно более независимы . . . . . . . . . . . . . . . . 212
Знайте свою библиотеку . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Потоково-безопасные коллекции ............................................ 213
Знайте модели выполнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
Модель «производители-потребители» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
Модель «читатели-писатели» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Модель «обедающих философов» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Остерегайтесь зависимостей между синхронизированными методами . . . . . . . . . . . . 216
Синхронизированные секции должны иметь минимальный размер . . . . . . . . . . . . . . . 216
О трудности корректного завершения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Тестирование многопоточного кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
Рассматривайте непериодические сбои как признаки возможных проблем
многопоточности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
Начните с отладки основного кода, не связанного с многопоточностью . . . . . . . . 219
Реализуйте переключение конфигураций многопоточного кода . . . . . . . . . . . . . . . 219
Обеспечьте логическую изоляцию конфигураций многопоточного кода . . . . . . . 219
Протестируйте программу с количеством потоков, превышающим
количество процессоров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
Протестируйте программу на разных платформах . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
9
10   ﻿Содержание
Применяйте инструментовку кода для повышения вероятности сбоев . . . . . . . . 220
Ручная инструментовка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Автоматизированная инструментовка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
Глава 14. Последовательное очищение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
Реализация Args . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Как я это сделал? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Args: черновик . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
На этом я остановился . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
О постепенном усовершенствовании . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
Аргументы String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
Глава 15. Внутреннее строение JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
Инфраструктура JUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
Глава 16. Переработка SerialDate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
Прежде всего — заставить работать . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
…Потом очистить код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
Глава 17. Запахи и эвристические правила . . . . . . . . . . . . . . . . . . . . . . . . . . 322
Комментарии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
C1: Неуместная информация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
C2: Устаревший комментарий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
C3: Избыточный комментарий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
C4: Плохо написанный комментарий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
C5: Закомментированный код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Рабочая среда . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
E1: Построение состоит из нескольких этапов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
E2: Тестирование состоит из нескольких этапов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
F1: Слишком много аргументов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
F2: Выходные аргументы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
F3: Флаги в аргументах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
F4: Мертвые функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
Разное . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
G1: Несколько языков в одном исходном файле . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
G2: Очевидное поведение не реализовано . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
G3: Некорректное граничное поведение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
G4: Отключенные средства безопасности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
G5: Дублирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
G6: Код на неверном уровне абстракции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328
G7: Базовые классы, зависящие от производных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
10
Оглавление   11
G8: Слишком много информации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
G9: Мертвый код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
G10: Вертикальное разделение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
G11: Непоследовательность . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
G12: Балласт . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
G13: Искусственные привязки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
G14: Функциональная зависть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
G15: Аргументы-селекторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
G16: Непонятные намерения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
G17: Неверное размещение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
G18: Неуместные статические методы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
G19: Используйте пояснительные переменные . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
G20: Имена функций должны описывать выполняемую операцию . . . . . . . . . . . . 335
G21: Понимание алгоритма . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
G22: Преобразование логических зависимостей в физические . . . . . . . . . . . . . . . . 336
G23: Используйте полиморфизм вместо if/Else или switch/Case . . . . . . . . . . . . . . 338
G24: Соблюдайте стандартные конвенции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
G25: Заменяйте «волшебные числа» именованными константами . . . . . . . . . . . . . 339
G26: Будьте точны . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
G27: Структура важнее конвенций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
G28: Инкапсулируйте условные конструкции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
G29: Избегайте отрицательных условий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
G30: Функции должны выполнять одну операцию . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
G31: Скрытые временн*
ые привязки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
G32: Структура кода должна быть обоснована . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
G33: Инкапсулируйте граничные условия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
G34: Функции должны быть написаны на одном уровне абстракции . . . . . . . . . . 344
G35: Храните конфигурационные данные на высоких уровнях . . . . . . . . . . . . . . . . 345
G36: Избегайте транзитивных обращений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
J1: Используйте обобщенные директивы импорта . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
J2: Не наследуйте от констант . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
J3: Константы против перечислений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Имена . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
N1: Используйте содержательные имена . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
N2: Выбирайте имена на подходящем уровне абстракции . . . . . . . . . . . . . . . . . . . . . 351
N3: По возможности используйте стандартную номенклатуру . . . . . . . . . . . . . . . . 352
N4: Недвусмысленные имена . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
N5: Используйте длинные имена для длинных областей видимости . . . . . . . . . . . 353
N6: Избегайте кодирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
N7: Имена должны описывать побочные эффекты . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
Тесты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
T1: Нехватка тестов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
T2: Используйте средства анализа покрытия кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
T3: Не пропускайте тривиальные тесты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
T4: Отключенный тест как вопрос . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
T5: Тестируйте граничные условия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
T6: Тщательно тестируйте код рядом с ошибками . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
11
12   ﻿Содержание
T7: Закономерности сбоев часто несут полезную информацию . . . . . . . . . . . . . . . . 355
T8: Закономерности покрытия кода часто несут полезную информацию . . . . . . 355
T9: Тесты должны работать быстро . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Литература . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Приложение А. Многопоточность II . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
Пример приложения «клиент/сервер» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
Знайте свои библиотеки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
Зависимости между методами могут нарушить работу многопоточного кода . . . . . . 370
Повышение производительности . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
Взаимная блокировка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Тестирование многопоточного кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
Средства тестирования многопоточного кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
Полные примеры кода . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
Приложение Б. org.jfree.date.SerialDate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
Приложение В. Перекрестные ссылки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
Эпилог . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
Алфавитный указатель . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459